/////*++
////
////Copyright (c) Microsoft Corporation All Rights Reserved
////
////Module Name:
////
////    BusPdo.c
////
////Abstract:
////
////    This module handles plug & play calls for the child device (PDO).
////
////Environment:
////
////    kernel mode only
////
////--*/
////
////#include "busenum.h"
////
////ULONG BusEnumDebugLevel;
////
////#ifdef ALLOC_PRAGMA
////#pragma alloc_text(PAGE, Bus_CreatePdo)
////#endif
////
////#define MAX_ID_LEN 80
////
////NTSTATUS
////Bus_CreatePdo(
////    _In_ WDFDEVICE  Device,
////    _In_ PWSTR      HardwareIds,
////    _In_ ULONG      SerialNo
////)
/////*++
////
////Routine Description:
////
////    This routine creates and initialize a PDO.
////
////Arguments:
////
////Return Value:
////
////    NT Status code.
////
////--*/
////{
////    NTSTATUS                    status;
////    PWDFDEVICE_INIT             pDeviceInit = NULL;
////    PPDO_DEVICE_DATA            pdoData = NULL;
////    WDFDEVICE                   hChild = NULL;
////    WDF_QUERY_INTERFACE_CONFIG  qiConfig;
////    WDF_OBJECT_ATTRIBUTES       pdoAttributes;
////    WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
////    WDF_DEVICE_POWER_CAPABILITIES powerCaps;
////    TOASTER_INTERFACE_STANDARD  ToasterInterface;
////    DECLARE_CONST_UNICODE_STRING(compatId, BUSENUM_COMPATIBLE_IDS);
////    DECLARE_CONST_UNICODE_STRING(deviceLocation, L"Toaster Bus 0");
////    UNICODE_STRING deviceId;
////    DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN);
////
////    KdPrint(("BusEnum: Entered Bus_CreatePdo\n"));
////
////    PAGED_CODE();
////
////    //
////    // Allocate a WDFDEVICE_INIT structure and set the properties
////    // so that we can create a device object for the child.
////    //
////    pDeviceInit = WdfPdoInitAllocate(Device);
////
////    if (pDeviceInit == NULL) {
////        status = STATUS_INSUFFICIENT_RESOURCES;
////        goto Cleanup;
////    }
////
////    //
////    // Set DeviceType
////    //
////    WdfDeviceInitSetDeviceType(pDeviceInit, FILE_DEVICE_BUS_EXTENDER);
////
////    //
////    // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId
////    //
////    RtlInitUnicodeString(&deviceId,HardwareIds);
////
////    status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId);
////    if (!NT_SUCCESS(status)) {
////        goto Cleanup;
////    }
////
////    //
////    // Note same string  is used to initialize hardware id too
////    //
////    status = WdfPdoInitAddHardwareID(pDeviceInit, &deviceId);
////    if (!NT_SUCCESS(status)) {
////        goto Cleanup;
////    }
////
////    status = WdfPdoInitAddCompatibleID(pDeviceInit, &compatId);
////    if (!NT_SUCCESS(status)) {
////        goto Cleanup;
////    }
////
////    status =  RtlUnicodeStringPrintf(&buffer, L"%02d", SerialNo);
////    if (!NT_SUCCESS(status)) {
////        goto Cleanup;
////    }
////
////    status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer);
////    if (!NT_SUCCESS(status)) {
////        goto Cleanup;
////    }
////
////    //
////    // Provide a description about the device. This text is usually read from
////    // the device. In the case of USB device, this text comes from the string
////    // descriptor. This text is displayed momentarily by the PnP manager while
////    // it's looking for a matching INF. If it finds one, it uses the Device
////    // Description from the INF file or the friendly name created by
////    // coinstallers to display in the device manager. FriendlyName takes
////    // precedence over the DeviceDesc from the INF file.
////    //
////    status = RtlUnicodeStringPrintf(&buffer,L"Microsoft_Eliyas_Toaster_%02d", SerialNo );
////    if (!NT_SUCCESS(status)) {
////        goto Cleanup;
////    }
////
////    //
////    // You can call WdfPdoInitAddDeviceText multiple times, adding device
////    // text for multiple locales. When the system displays the text, it
////    // chooses the text that matches the current locale, if available.
////    // Otherwise it will use the string for the default locale.
////    // The driver can specify the driver's default locale by calling
////    // WdfPdoInitSetDefaultLocale.
////    //
////    status = WdfPdoInitAddDeviceText(pDeviceInit,
////                                        &buffer,
////                                        &deviceLocation,
////                                        0x409);
////    if (!NT_SUCCESS(status)) {
////        goto Cleanup;
////    }
////
////    WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409);
////
////    //
////    // Initialize the attributes to specify the size of PDO device extension.
////    // All the state information private to the PDO will be tracked here.
////    //
////    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, PDO_DEVICE_DATA);
////
////    status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild);
////    if (!NT_SUCCESS(status)) {
////        goto Cleanup;
////
////    }
////
////    //
////    // Once the device is created successfully, framework frees the
////    // DeviceInit memory and sets the pDeviceInit to NULL. So don't
////    // call any WdfDeviceInit functions after that.
////    //
////    // Get the device context.
////    //
////    pdoData = PdoGetData(hChild);
////
////    pdoData->SerialNo = SerialNo;
////
////    //
////    // Set some properties for the child device.
////    //
////    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
////    pnpCaps.Removable         = WdfTrue;
////    pnpCaps.EjectSupported    = WdfTrue;
////    pnpCaps.SurpriseRemovalOK = WdfTrue;
////
////    pnpCaps.Address  = SerialNo;
////    pnpCaps.UINumber = SerialNo;
////
////    WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);
////
////    WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps);
////
////    powerCaps.DeviceD1 = WdfTrue;
////    powerCaps.WakeFromD1 = WdfTrue;
////    powerCaps.DeviceWake = PowerDeviceD1;
////
////    powerCaps.DeviceState[PowerSystemWorking]   = PowerDeviceD0;
////    powerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
////    powerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
////    powerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
////    powerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
////    powerCaps.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
////
////    WdfDeviceSetPowerCapabilities(hChild, &powerCaps);
////
////    //
////    // Create a custom interface so that other drivers can
////    // query (IRP_MN_QUERY_INTERFACE) and use our callbacks directly.
////    //
////    RtlZeroMemory(&ToasterInterface, sizeof(ToasterInterface));
////
////    ToasterInterface.InterfaceHeader.Size = sizeof(ToasterInterface);
////    ToasterInterface.InterfaceHeader.Version = 1;
////    ToasterInterface.InterfaceHeader.Context = (PVOID) hChild;
////
////    //
////    // Let the framework handle reference counting.
////    //
////    ToasterInterface.InterfaceHeader.InterfaceReference =
////        WdfDeviceInterfaceReferenceNoOp;
////    ToasterInterface.InterfaceHeader.InterfaceDereference =
////        WdfDeviceInterfaceDereferenceNoOp;
////
////    ToasterInterface.GetCrispinessLevel  = Bus_GetCrispinessLevel;
////    ToasterInterface.SetCrispinessLevel  = Bus_SetCrispinessLevel;
////    ToasterInterface.IsSafetyLockEnabled = Bus_IsSafetyLockEnabled;
////
////    WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig,
////                                    (PINTERFACE) &ToasterInterface,
////                                    &GUID_TOASTER_INTERFACE_STANDARD,
////                                    NULL);
////    //
////    // If you have multiple interfaces, you can call WdfDeviceAddQueryInterface
////    // multiple times to add additional interfaces.
////    //
////    status = WdfDeviceAddQueryInterface(hChild, &qiConfig);
////    if (!NT_SUCCESS(status)) {
////        goto Cleanup;
////
////    }
////
////    //
////    // Add this device to the FDO's collection of children.
////    // After the child device is added to the static collection successfully,
////    // driver must call WdfPdoMarkMissing to get the device deleted. It
////    // shouldn't delete the child device directly by calling WdfObjectDelete.
////    //
////    status = WdfFdoAddStaticChild(Device, hChild);
////    if (!NT_SUCCESS(status)) {
////        goto Cleanup;
////    }
////
////    return status;
////
////Cleanup:
////    KdPrint(("BusEnum: Bus_CreatePdo failed %x\n", status));
////
////    //
////    // Call WdfDeviceInitFree if you encounter an error before the
////    // device is created. Once the device is created, framework
////    // NULLs the pDeviceInit value.
////    //
////    if (pDeviceInit != NULL) {
////        WdfDeviceInitFree(pDeviceInit);
////    }
////
////    if(hChild) {
////        WdfObjectDelete(hChild);
////    }
////
////    return status;
////}
////
////
////BOOLEAN
////Bus_GetCrispinessLevel(
////    IN   WDFDEVICE ChildDevice,
////    OUT  PUCHAR Level
////    )
/////*++
////
////Routine Description:
////
////    This routine gets the current crispiness level of the toaster.
////
////Arguments:
////
////    Context        pointer to  PDO device extension
////    Level          crispiness level of the device
////
////Return Value:
////
////    TRUE or FALSE
////
////--*/
////{
////    UNREFERENCED_PARAMETER(ChildDevice);
////
////    //
////    // Validate the context to see if it's really a pointer
////    // to PDO's device extension. You can store some kind
////    // of signature in the PDO for this purpose
////    //
////
////    KdPrint(("BusEnum: GetCrispnessLevel\n"));
////
////    *Level = 10;
////    return TRUE;
////}
////
////BOOLEAN
////Bus_SetCrispinessLevel(
////    IN   WDFDEVICE ChildDevice,
////    IN   UCHAR     Level
////    )
/////*++
////
////Routine Description:
////
////    This routine sets the current crispiness level of the toaster.
////
////Arguments:
////
////    Context        pointer to  PDO device extension
////    Level          crispiness level of the device
////
////Return Value:
////
////    TRUE or FALSE
////
////--*/
////{
////    UNREFERENCED_PARAMETER(ChildDevice);
////    UNREFERENCED_PARAMETER(Level);
////
////    KdPrint(("BusEnum: SetCrispnessLevel\n"));
////
////    return TRUE;
////}
////
////BOOLEAN
////Bus_IsSafetyLockEnabled(
////    IN   WDFDEVICE ChildDevice
////    )
/////*++
////
////Routine Description:
////
////    Routine to check whether safety lock is enabled
////
////Arguments:
////
////    Context        pointer to  PDO device extension
////
////Return Value:
////
////    TRUE or FALSE
////
////--*/
////{
////    UNREFERENCED_PARAMETER(ChildDevice);
////
////    KdPrint(("BusEnum: IsSafetyLockEnabled\n"));
////
////    return TRUE;
////}
////
